package com.epam.grsulab.webapi.web.pages.data;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;

import com.epam.grsulab.webapi.dao.base.Dao;
import com.epam.grsulab.webapi.entity.base.BaseEntity;

/**
 * @author dmitry_zhivushko
 * @since 27.11.2013
 */
@SuppressWarnings("serial")
public class DBTableComponent extends Panel {

	public DBTableComponent(final String id, final Dao<? extends BaseEntity> dao) {
		super(id);

		final Class<? extends BaseEntity> domainClass = dao.getDomainClass();
		add(new Label("tableName", domainClass.getSimpleName()));
		final List<Field> declaredFields = getORMProperties(domainClass);

		createTableHeader(declaredFields);
		createTableBody(dao, declaredFields);

	}

	private List<Field> getORMProperties(final Class<? extends BaseEntity> domainClass) {

		final List<Field> result = new ArrayList<Field>();

		final Field[] declaredFields = domainClass.getDeclaredFields();
		for (final Field field : declaredFields) {

			if (field.getAnnotation(javax.persistence.Id.class) != null || field.getAnnotation(javax.persistence.Column.class) != null
					|| field.getAnnotation(javax.persistence.ManyToOne.class) != null) {
				result.add(field);
			}
		}

		return result;
	}

	private void createTableBody(final Dao<? extends BaseEntity> dao, final List<Field> declaredFields) {
		final List<? extends BaseEntity> entities = dao.findAll();

		add(new ListView<BaseEntity>("rows", entities) {

			@Override
			protected void populateItem(final ListItem<BaseEntity> item) {

				final List<String> list = getOrderedValues(item, declaredFields);

				item.add(new ListView<String>("values", list) {

					@Override
					protected void populateItem(final ListItem<String> value) {
						value.add(new Label("value", value.getModelObject()));
					}
				});

			}

		});
	}

	private List<String> getOrderedValues(final ListItem<BaseEntity> item, final List<Field> declaredFields) {
		final BaseEntity modelObject = item.getModelObject();
		final ArrayList<String> arrayList = new ArrayList<String>();
		for (final Field field : declaredFields) {
			field.setAccessible(true);
			final Class<?> type = field.getType();
			try {
				Object object = field.get(modelObject);
				if (type.isPrimitive()) {
					arrayList.add(String.valueOf(object));
				} else if (Enum.class.isAssignableFrom(type)) {
					arrayList.add(String.valueOf(object));
				} else if (Object.class.isAssignableFrom(type)) {
					arrayList.add(object != null ? object.toString() : "null");
				} else {
					throw new IllegalArgumentException(String.format("Type '%s' is not supported . You need to adjust code. Class name: %s", type, modelObject
							.getClass().getName()));
				}
			} catch (final Exception e) {
				throw new RuntimeException(e);
			}
		}
		return arrayList;
	}

	private void createTableHeader(final List<Field> declaredFields) {
		add(new ListView<Field>("tableHeader", declaredFields) {

			/**
			 * 
			 */
			private static final long serialVersionUID = 1165782605744323789L;

			@Override
			protected void populateItem(final ListItem<Field> item) {
				item.add(new Label("name", item.getModelObject().getName()));
			}
		});
	}

}
